package com.hwtx.form.util;

import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import static com.hwtx.form.domain.FormConstants.TYPE_KEY;

public class JsonFinder {

    /**
     * 查找type为targetType的节点，检查父节点链中是否包含stopType
     */
    public static void findNodesWithParentCheck(JsonNode root, String targetType,
                                                List<String> stopType, Consumer<NodeInfo> consumer) {
        findNodesWithParentChain(root, "", null, new ArrayList<>(), targetType, stopType, consumer);
    }

    /**
     * 递归方法，维护完整的父节点链
     */
    private static void findNodesWithParentChain(JsonNode currentNode, String currentPath,
                                                 JsonNode parentNode, List<JsonNode> parentChain,
                                                 String targetType, List<String> stopType, Consumer<NodeInfo> consumer) {

        // 创建当前节点的父节点链副本（避免修改原始链）
        List<JsonNode> currentParentChain = new ArrayList<>(parentChain);
        if (parentNode != null) {
            currentParentChain.add(parentNode);
        }

        // 检查当前节点是否为targetType
        if (isTypeNode(currentNode, targetType)) {
            // 检查父节点链中是否包含stopType
            boolean hasStopType = false;
            if (CollectionUtils.isNotEmpty(stopType)) {
                for (JsonNode ancestor : currentParentChain) {
                    if (isStopNode(ancestor, stopType)) {
                        hasStopType = true;
                        break;
                    }
                }
            }

            if (!hasStopType) {
                // 父节点链中不包含stopType，添加到结果
                if (consumer != null) {
                    consumer.accept(new NodeInfo(currentNode, currentPath, parentNode, currentParentChain));
                }
            }
            return; // 找到目标节点后停止当前分支的继续搜索
        }

        // 递归遍历子节点
        if (currentNode.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> fields = currentNode.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> entry = fields.next();
                String fieldName = entry.getKey();
                JsonNode childNode = entry.getValue();
                String childPath = buildPath(currentPath, fieldName);

                findNodesWithParentChain(childNode, childPath, currentNode,
                        currentParentChain, targetType, stopType, consumer);
            }
        } else if (currentNode.isArray()) {
            for (int i = 0; i < currentNode.size(); i++) {
                JsonNode childNode = currentNode.get(i);
                String childPath = buildPath(currentPath, String.valueOf(i));

                findNodesWithParentChain(childNode, childPath, currentNode,
                        currentParentChain, targetType, stopType, consumer);
            }
        }
    }

    static boolean isStopNode(JsonNode node, List<String> stopValues) {
        if (CollectionUtils.isEmpty(stopValues)) {
            return false;
        }
        return stopValues.stream().anyMatch(stopValue -> isTypeNode(node, stopValue));
    }

    /**
     * 检查节点是否为指定类型
     */
    static boolean isTypeNode(JsonNode node, String typeValue) {
        if (node == null || !node.isObject()) {
            return false;
        }
        JsonNode typeField = node.get(TYPE_KEY);
        return typeField != null && typeField.isTextual() && typeValue.equals(typeField.asText());
    }

    private static String buildPath(String parentPath, String segment) {
        return parentPath.isEmpty() ? segment : parentPath + "/" + segment;
    }

    /**
     * 增强的节点信息类，包含父节点链
     */
    public record NodeInfo(JsonNode node, String path, JsonNode parentNode, List<JsonNode> parentChain) {

        public String getType() {
            if (node != null && node.isObject()) {
                JsonNode typeField = node.get(TYPE_KEY);
                if (typeField != null && typeField.isTextual()) {
                    return typeField.asText();
                }
            }
            return null;
        }

        /**
         * 获取父节点链中的类型列表
         */
        public List<String> getParentChainTypes() {
            List<String> types = new ArrayList<>();
            for (JsonNode parent : parentChain) {
                if (parent != null && parent.isObject()) {
                    JsonNode typeField = parent.get(TYPE_KEY);
                    if (typeField != null && typeField.isTextual()) {
                        types.add(typeField.asText());
                    } else {
                        types.add("NO_TYPE");
                    }
                }
            }
            return types;
        }

        @Override
        public @NotNull String toString() {
            return String.format("Path: %s, Type: %s, ParentChainTypes: %s",
                    path, getType(), getParentChainTypes());
        }
    }
}